/**
 * 
 */
package com.goldentrail.neo4j;

import java.util.ArrayList;

import org.json.JSONException;
import org.json.JSONObject;

/**
 * Specification of a path for Neo4jNode.findPath(s). doesn't specify start node because it is called on an existing Neo4jNode
 * @author mikeagun
 *
 */
public class PathSpec {
	public static final String SHORTEST_PATH = "shortestPath";
	public static final String ALL_PATHS = "allPaths";
	public static final String ALL_SIMPLE_PATHS = "allSimplePaths";
	public static final String DIJKSTRA = "dijkstra";
	
	private Neo4jNode toNode = null;
	private ArrayList<RelationshipSpec> relationships = null;
	private int maxDepth = -1;
	private Boolean maxDepthSet = false;
	private String algorithm = null;
	
	private static final String RELATIONSHIPS = "relationships";
	private static final String MAX_DEPTH = "max_depth";
	private static final String ALGORITHM = "algorithm";
	private static final String TO = "to";
	
	/**
	 * @return the maxDepth
	 */
	public int getMaxDepth() {
		return maxDepth;
	}

	/**
	 * @param maxDepth
	 *            the maxDepth to set
	 */
	public void setMaxDepth(int maxDepth) {
		maxDepthSet = true;
		this.maxDepth = maxDepth;
	}

	/**
	 * @return the algorithm
	 */
	public String getAlgorithm() {
		return algorithm;
	}

	/**
	 * Sets the algorithm used for path finding. should be one of: SHORTEST_PATH, ALL_PATHS, ALL_SIMPLE_PATHS, DIJKSTRA
	 * @param algorithm the algorithm to set
	 */
	public void setAlgorithm(String algorithm) {
		this.algorithm = algorithm;
	}

	/**
	 * Gets The node to find paths to.
	 * @return the toNode
	 */
	public Neo4jNode getToNode() {
		return toNode;
	}

	/**
	 * Sets The node to find paths to.
	 * @param toNode the toNode to set
	 */
	public void setToNode(Neo4jNode toNode) {
		this.toNode = toNode;
	}

	/**
	 * Gets the relationships that are to be traversed and their directions
	 * @return the relationships
	 */
	public ArrayList<RelationshipSpec> getRelationships() {
		return relationships;
	}

	/**
	 * Sets the relationships that are to be traversed and their directions
	 * @param relationships the relationships to set
	 */
	public void setRelationships(ArrayList<RelationshipSpec> relationships) {
		this.relationships = relationships;
	}
	
	/**
	 * Gets the JSONObject representing a path specification that can then be sent to the server to initiate path finding
	 * @return JSONObject representing path specification
	 */
	public JSONObject getJson() {
		try {
			JSONObject json = new JSONObject();
			if (algorithm == null || toNode == null || relationships == null)
				return null;
			if (maxDepthSet)
				json.put(MAX_DEPTH, maxDepth);
			json.put(ALGORITHM, algorithm);
			json.put(TO, toNode.getURI().toString());
			for (RelationshipSpec rel : relationships) {
				json.accumulate(RELATIONSHIPS, rel.getJson());
			}
			
			return json;
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		JSONObject json = getJson();
		if (json == null)
			return null;
		else
			return json.toString();
	}
	
}
